package main.leetcode.clockin.April;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 面试题13.机器人的运动范围
 *
 * <p>地上有一个m行n列的方格，从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0]
 * 的格子开始移动，它每次可以向左、右、上、下移动一格（不能移动到方格外），也不能进入行坐标和列坐标的数位之和大于k的格子。例如，当k为18时，机器人能够进入方格 [35, 37]
 * ，因为3+5+3+7=18。但它不能进入方格 [35, 38]，因为3+5+3+8=19。请问该机器人能够到达多少个格子？
 *
 * <p>
 *
 * <p>示例 1：输入：m = 2, n = 3, k = 1 输出：3
 *
 * <p>示例 1：输入：m = 3, n = 1, k = 0 输出：1
 *
 * <p>提示：1 <= n,m <= 100 0 <= k <= 20
 *
 * <p>来源：力扣（LeetCode） 链接：https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class day8 {
    public static void main(String[] args) {
        System.out.println(new day8().movingCount(16, 8, 4));
    }
    // dfs
    //    public int movingCount(int m, int n, int k) {
    //        if (k == 0) return 1;
    //        boolean[][] isVisited = new boolean[m][n];
    //        return dfs(isVisited, m, n, 0, 0, k);
    //    }

    private int dfs(boolean[][] isVisited, int m, int n, int i, int j, int k) {
        if (i < 0 || i > m - 1 || j < 0 || j > n - 1 || isVisited[i][j]) return 0;
        isVisited[i][j] = true;
        int sum = 0;
        int row = i, col = j;
        while (row > 0) {
            sum += row % 10;
            row /= 10;
        }
        while (col > 0) {
            sum += col % 10;
            col /= 10;
        }
        if (sum > k) return 0;
        else
            return 1
                    //                    + dfs(isVisited, m, n, i - 1, j, k) // 上
                    + dfs(isVisited, m, n, i + 1, j, k) // 下
                    //                    + dfs(isVisited, m, n, i, j - 1, k) // 左
                    + dfs(isVisited, m, n, i, j + 1, k); // 右
    }

    // bfs
    public int movingCount(int m, int n, int k) {
        if (k == 0) return 1;
        boolean[][] isVisited = new boolean[m][n];
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[] {0, 0});
        int i, j, res = 0;
        int[] tmp;
        while (!queue.isEmpty()) {
            tmp = queue.poll();
            i = tmp[0];
            j = tmp[1];
            if (i < 0 || i > m - 1 || j < 0 || j > n - 1 || isVisited[i][j] || compare(i, j, k))
                continue;
            isVisited[i][j] = true;
            ++res;
            queue.add(new int[] {i + 1, j});
            queue.add(new int[] {i, j + 1});
        }
        return res;
    }

    private boolean compare(int i, int j, int k) {
        int sum = 0;
        while (i > 0) {
            sum += i % 10;
            i /= 10;
        }
        while (j > 0) {
            sum += j % 10;
            j /= 10;
        }
        return sum > k;
    }
}
